﻿using FastExecutor.Base.Util;
using FastIOC.Annotation;
using FastIOC.Builder;
using FastORM.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
using System.Web.Routing;

namespace FastExecutor.Base.Design
{
    public class FastControllerFactory : DefaultControllerFactory
    {
        public override IController CreateController(RequestContext requestContext, string controllerName)
        {
            Type type = this.GetControllerType(requestContext, controllerName);
            Object obj = GetControllerInstance(requestContext, type);

            //自定义DB自动替换
            //因为Controller中存在一些自动注入的类，这里替换只是未标记AutoWired的模板DB ypeng 20190609
            List<FieldInfo> CustomDBFieldList = type.GetFields().Where(f => f.GetCustomAttribute(typeof(AutoWired)) == null && CommonUtil.IsAssignableFrom(f.FieldType, typeof(IFastBaseDB<>))).ToList();
            List<Type> CustomDBTypeList = InjectUtil.Container.GetRegistType(typeof(IFastBaseDB<>));
            foreach (FieldInfo field in CustomDBFieldList)
            {
                //因为Controller中DB是父类中的泛型类，所以直接使用GetGenericArguments()[0].Name获取泛型T的具体类名
                //自定义的DB类是普通类，所以要通过a.BaseType.GetGenericArguments()[0].Name获取泛型T的具体类名
                List<Type> CustomDBTypeFilterList = CustomDBTypeList.Where(a => a.BaseType.GetGenericArguments().Count() > 0 && a.BaseType.GetGenericArguments()[0].Name == field.FieldType.GetGenericArguments()[0].Name).ToList();
                if (CustomDBTypeFilterList.Count > 0)
                {
                    //进行注入
                    field.SetValue(obj, InjectUtil.Container.Resolve(CustomDBTypeFilterList[0]));
                }
                else
                {
                    //没有对应的DB泛型类重写实现实例的，实例化一个默认的FastTemplateDB
                    field.SetValue(obj, InjectUtil.Container.ResolveGeneric(typeof(FastTemplateDB<>), field.FieldType.GetGenericArguments()));
                }
            }

            //Controller中标记AutoWired属性的自动注入
            List<FieldInfo> AutoWiredFieldList = type.GetRuntimeFields().Where(f => f.GetCustomAttribute(typeof(AutoWired)) != null).ToList();
            foreach (FieldInfo field in AutoWiredFieldList)
            {
                field.SetValue(obj, InjectUtil.Container.Resolve(field.FieldType));
            }


            return obj as IController;
        }

        protected override Type GetControllerType(RequestContext requestContext, string controllerName)
        {
            Type ControllerType = PluginUtil.GetControllerType(controllerName + "Controller");
            if (ControllerType == null)
            {
                ControllerType = base.GetControllerType(requestContext, controllerName);
            }
            return ControllerType;
        }
    }
}
